package cn.hznc.mqtt;

import cn.hutool.core.util.ObjectUtil;
import cn.hznc.configuration.SystemInit;
import cn.hznc.domain.entity.MachineToolStatus;
import cn.hznc.domain.entity.ProgramDurationTimeEntity;
import cn.hznc.utils.CommonUtil;
import cn.hznc.mapper.MachineToolStatusMapper;
import cn.nerc.nclink.core.general.InvalidException;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.commons.lang.StringUtils;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeoutException;


@Service
public class MqttService {

    private static final ConcurrentHashMap<String, String> equipmentGroupMap = new ConcurrentHashMap<>();

    @Value("${spring.mqtt.username}")
    private String username;

    @Value("${spring.mqtt.password}")
    private String password;

    @Value("${spring.mqtt.url}")
    private String hostUrl;

    @Value("${spring.mqtt.client.id}")
    private String clientId;

    @Value("${spring.mqtt.default.topic}")
    private String defaultTopic;


    private Logger logger = LoggerFactory.getLogger(getClass());

    @Resource
    private MachineToolStatusMapper machineToolStatusMapper;

    @Resource
    private SystemInit systemInit;

    private int get_waringId_index = -1;

    private int get_part_cnt_index = -1; //加工计件的id的索引

    static {
        equipmentGroupMap.put("1000E0DC000021", "西门子");//B2
        equipmentGroupMap.put("1000E0DC0001DB", "西门子");//B3
        equipmentGroupMap.put("1000E0DC00017E", "西门子");//B4
        equipmentGroupMap.put("1000E0DC0001BE", "西门子");//B5
        equipmentGroupMap.put("1000E0DC00025E", "西门子");//B6
        equipmentGroupMap.put("1000E0DC0001FB", "海德汉");//B11
        equipmentGroupMap.put("1000E0DC0001DC", "海德汉");//B12
        equipmentGroupMap.put("1000E0DC000246", "海德汉");//B17
        equipmentGroupMap.put("1000E0DC0001E1", "科德");//B13
        equipmentGroupMap.put("1000E0DC000011", "科德");//B14
        equipmentGroupMap.put("1000E0DC00022C", "科德");//B15
        equipmentGroupMap.put("1000E0DC00016F", "科德");//B16
    }

    private String getDataByIndex(JSONArray dataArray, Integer index) {
        String dataStr = JSONObject.toJSONString(dataArray.get(index));
        JSONObject statusObject = JSONArray.parseObject(dataStr);
        return CommonUtil.getProgramReload(statusObject.get("data"));
    }

    private String getDataByIndexReload(JSONArray dataArray, Integer index) {
        String s = JSONObject.toJSONString(dataArray.get(index));
        JSONObject jsonObject = JSONArray.parseObject(s);
        return CommonUtil.getProgramString(jsonObject);
    }

    private String splitStatus(String status){
        if(StringUtils.isNotBlank(status)){
            String[] split = status.split(",");
            return split[0];
        }
        return status;
    }

    private void parseKD(JSONArray dataArray, String snCode) {
         List<ProgramDurationTimeEntity> insertDurationList = new ArrayList<>();
        //获取状态
        String status = getDataByIndex(dataArray, 0);
        status = splitStatus(status);
        if (SystemInit.statusMap.getOrDefault(snCode, "").equals("")) {
            SystemInit.statusMap.put(snCode, status);
        }

        //获取加工件数
        String partCount = getDataByIndex(dataArray, 1);

        //获取报警状态
        //String alarm = getDataByIndexReload(dataArray, 2);

        //获取加工起止时间
        //String startTime = getDataByIndexReload(dataArray, 3);

        //获取进给速度
        String feedSpeed = getDataByIndex(dataArray, 4);


        //获取进给倍率
        String feedOverride = getDataByIndex(dataArray, 5);

        //获取主轴倍率
        String spindleOverride = getDataByIndex(dataArray, 6);

        //获取主轴转速
        String spindleSpeed = getDataByIndex(dataArray, 7);

         //获取主程序名
        String program = getDataByIndex(dataArray , 8);

         if (SystemInit.programMap.getOrDefault(snCode, "").equals("")) {
             SystemInit.programMap.put(snCode, status);
         }
         MachineToolStatus machineToolStatus = new MachineToolStatus();
         if(!program.equals(SystemInit.programMap.get(snCode)) || !status.equals(SystemInit.statusMap.get(snCode))){
             QueryWrapper<MachineToolStatus> wrapper = new QueryWrapper<>();
             wrapper.orderByDesc("create_time");
             wrapper.eq("sn_code", snCode);
             wrapper.last("LIMIT 1");
             MachineToolStatus existStatus = machineToolStatusMapper.selectOne(wrapper);
             if (ObjectUtil.isNotNull(existStatus)) {
                 machineToolStatus.setTime(new Date().getTime() - existStatus.getCreateTime().getTime());
             }
             machineToolStatus.setSnCode(snCode);
             machineToolStatus.setStatus(status);
             machineToolStatus.setProgram(program);
             //machineToolStatus.setSubProgram(subProgram);
             machineToolStatus.setCreateTime(new Date());
             if (ObjectUtil.isNotNull(machineToolStatus) && ObjectUtil.isNotNull(machineToolStatus.getTime()) && machineToolStatus.getTime() - 0.0 > 0.000001) {
                 if(StringUtils.isBlank(machineToolStatus.getStatus())){
                     machineToolStatus.setStatus("offline");
                 }
                 machineToolStatusMapper.insert(machineToolStatus);
                 if (status.equals("running")) {
                     systemInit.buildInsertDurationListReload(insertDurationList, SystemInit.programMap.get(snCode), snCode, machineToolStatus.getTime(), feedSpeed, feedOverride, spindleSpeed);
                 }

         }   }
        SystemInit.statusMap.put(snCode, status);
        SystemInit.programMap.put(snCode, program);

    }

    private void parseHDH(JSONArray dataArray, String snCode) {
        List<ProgramDurationTimeEntity> insertDurationList = new ArrayList<>();

        //获取状态
        String status = getDataByIndex(dataArray, 0);
        status = splitStatus(status);
        if (SystemInit.statusMap.getOrDefault(snCode, "").equals("")) {
            SystemInit.statusMap.put(snCode, status);
        }
        //获取进给速度
        String feedSpeed = getDataByIndex(dataArray, 4);

        //获取进给倍率
        String feedOverride = getDataByIndex(dataArray, 5);

        //获取主轴倍率
        String spindleOverride = getDataByIndex(dataArray, 6);

        //获取主轴转速
        String spindleSpeed = getDataByIndex(dataArray, 7);

        //获取子程序名
        String subProgram = getDataByIndex(dataArray, 10);
        if (SystemInit.programMap.getOrDefault(snCode, "").equals("")) {
            SystemInit.programMap.put(snCode, subProgram);
        }
        //获取主程序名
        String program = getDataByIndex(dataArray, 8);
        MachineToolStatus machineToolStatus = new MachineToolStatus();
        String s = SystemInit.statusMap.get(snCode);
        String s1 = SystemInit.programMap.get(snCode);//获取报警状态
        if (!SystemInit.statusMap.get(snCode).equals(status) || !SystemInit.programMap.get(snCode).equals(subProgram)) {
            QueryWrapper<MachineToolStatus> wrapper = new QueryWrapper<>();
            wrapper.orderByDesc("create_time");
            wrapper.eq("sn_code", snCode);
            wrapper.last("LIMIT 1");
            MachineToolStatus existStatus = machineToolStatusMapper.selectOne(wrapper);
            if (ObjectUtil.isNotNull(existStatus)) {
                machineToolStatus.setTime(new Date().getTime() - existStatus.getCreateTime().getTime());
            }
            machineToolStatus.setSnCode(snCode);
            machineToolStatus.setStatus(status);
            machineToolStatus.setProgram(program);
            machineToolStatus.setSubProgram(subProgram);
            machineToolStatus.setCreateTime(new Date());
            if (ObjectUtil.isNotNull(machineToolStatus) && ObjectUtil.isNotNull(machineToolStatus.getTime()) && machineToolStatus.getTime() - 0.0 > 0.000001) {
                if(StringUtils.isBlank(machineToolStatus.getStatus())){
                    machineToolStatus.setStatus("offline");
                }
                machineToolStatusMapper.insert(machineToolStatus);
                if (status.equals("running")) {
                    systemInit.buildInsertDurationListReload(insertDurationList, SystemInit.programMap.get(snCode), snCode, machineToolStatus.getTime(), feedSpeed, feedOverride, spindleSpeed);
                }

            }
        }
        SystemInit.statusMap.put(snCode, status);
        SystemInit.programMap.put(snCode, subProgram);
        //获取加工件数
        String partCount = getDataByIndex(dataArray, 1);

        //获取报警状态
        //String alarm = getDataByIndex(dataArray, 2);

        //获取加工起止时间
        String startTime = getDataByIndex(dataArray, 3);

        //获取程序内容
        String programContent = getDataByIndex(dataArray, 9);


        //获取子程序名
        String yLocation = getDataByIndex(dataArray, 11);


        //获取子程序名
        String zLocation = getDataByIndex(dataArray, 12);


        //获取子程序名
        String xLocation = getDataByIndex(dataArray, 13);

//        machineToolStatus.setProgram(program);
//        machineToolStatus.setSubProgram(subProgram);
//        machineToolStatus.setCreateTime(new Date());
//        if (ObjectUtil.isNotNull(machineToolStatus) && ObjectUtil.isNotNull(machineToolStatus.getTime()) && machineToolStatus.getTime() - 0.0 > 0.000001) {
//            machineToolStatusMapper.insert(machineToolStatus);
//            if (status.equals("running")) {
//                systemInit.buildInsertDurationList(insertDurationList, SystemInit.programMap.get(snCode), snCode, machineToolStatus.getTime(), feedSpeed, feedOverride, spindleSpeed);
//            }
//
//        }
    }


    private void parseXMZ(JSONArray dataArray, String snCode) {
        List<ProgramDurationTimeEntity> insertDurationList = new ArrayList<>();
        //获取进给速度
        String feedSpeed = getDataByIndex(dataArray, 4);

        //获取进给倍率
        String feedOverride = getDataByIndex(dataArray, 5);

        //获取主轴倍率
        String spindleOverride = getDataByIndex(dataArray, 6);

        //获取主轴转速
        String spindleSpeed = getDataByIndex(dataArray, 7);


        //获取主程序名
        String program = getDataByIndex(dataArray, 8);


        //获取子程序
        String subProgram = getDataByIndex(dataArray, 18);
        if (SystemInit.programMap.getOrDefault(snCode, "").equals("")) {
            SystemInit.programMap.put(snCode, subProgram);

        }

        //获取状态
        String status = getDataByIndex(dataArray, 0);
        status = splitStatus(status);
        if (SystemInit.statusMap.getOrDefault(snCode, "").equals("")) {
            SystemInit.statusMap.put(snCode, status);
        }
//        if (SystemInit.statusMap.getOrDefault(snCode, "").equals("") || !status.equals(SystemInit.statusMap.getOrDefault(snCode, ""))) {
//        }
        MachineToolStatus machineToolStatus = new MachineToolStatus();//获取报警状态
        if (!SystemInit.statusMap.get(snCode).equals(status) || !SystemInit.programMap.get(snCode).equals(subProgram)) {
            QueryWrapper<MachineToolStatus> wrapper = new QueryWrapper<>();
            wrapper.orderByDesc("create_time");
            wrapper.eq("sn_code", snCode);//获取加工件数
            wrapper.last("LIMIT 1");
            //String partCount = getDataByIndex(dataArray, 1);
            MachineToolStatus existStatus = machineToolStatusMapper.selectOne(wrapper);
            machineToolStatus.setSnCode(snCode);
            if (ObjectUtil.isNotNull(existStatus)) {//String alarm = getDataByIndexReload(dataArray, 2);
                machineToolStatus.setTime(new Date().getTime() - existStatus.getCreateTime().getTime());
                machineToolStatus.setStatus(status);
                machineToolStatus.setProgram(program);
                machineToolStatus.setSubProgram(subProgram);
                machineToolStatus.setSnCode(snCode);
                if (SystemInit.programMap.getOrDefault(snCode, "").equals("") || !subProgram.equals(SystemInit.statusMap.getOrDefault(snCode, ""))) {
                    SystemInit.programMap.put(snCode, subProgram);
                }
                machineToolStatus.setCreateTime(new Date());
//                if (ObjectUtil.isNotNull(machineToolStatus) && ObjectUtil.isNotNull(machineToolStatus.getTime()) && machineToolStatus.getTime() - 0.0 > 0.000001) {
//                    machineToolStatusMapper.insert(machineToolStatus);
//                    if (status.equals("running")) {
//                        systemInit.buildInsertDurationListReload(insertDurationList, SystemInit.programMap.get(snCode), snCode, machineToolStatus.getTime(), feedSpeed, feedOverride, spindleSpeed);
//                    }
//                }


            }
        }
        SystemInit.statusMap.put(snCode, status);
        SystemInit.programMap.put(snCode, subProgram);
        //获取加工起止时间
        String startTime = getDataByIndex(dataArray, 3);

        //获取指令行号
        String line = getDataByIndex(dataArray, 9);

        //获取刀具号
        String toolNo = getDataByIndex(dataArray, 10);

        //X轴实际位置
        String xLocation = getDataByIndex(dataArray, 11);

        //Y轴实际位置
        String yLocation = getDataByIndex(dataArray, 12);

        //Z轴实际位置
        String zLocation = getDataByIndex(dataArray, 13);

        //负载百分比
        String loadOverride = getDataByIndex(dataArray, 14);

        //子程序名

        machineToolStatus.setProgram(program);
        machineToolStatus.setSubProgram(subProgram);
//        if (SystemInit.programMap.getOrDefault(snCode, "").equals("") || !subProgram.equals(SystemInit.statusMap.getOrDefault(snCode, ""))) {
//            SystemInit.programMap.put(snCode, subProgram);
//        }
        machineToolStatus.setCreateTime(new Date());
        if (ObjectUtil.isNotNull(machineToolStatus) && ObjectUtil.isNotNull(machineToolStatus.getTime()) && machineToolStatus.getTime() - 0.0 > 0.000001) {
            machineToolStatus.setStatus(status);
            if(StringUtils.isBlank(machineToolStatus.getStatus())){
                machineToolStatus.setStatus("offline");
            }
            machineToolStatusMapper.insert(machineToolStatus);
            if (status.equals("running")) {
                systemInit.buildInsertDurationListReload(insertDurationList, SystemInit.programMap.get(snCode), snCode, machineToolStatus.getTime(), feedSpeed, feedOverride, spindleSpeed);
            }
        }
    }


    public void handle_message(String topic, JSONObject message) throws ParseException, InterruptedException, InvalidException, TimeoutException, MqttException {

        if (topic.contains("Sample/")) {
            //sample_channel0
            if (topic.contains("sample_channel0")) {
               /* System.out.println(topic);
                System.out.println(message);*/
                String tmp[] = topic.split("/");
                String get_sn = tmp[1];
                //System.out.println("get_sn+message = " + get_sn + message);
                if(StringUtils.isNotBlank(get_sn)){
                   String s = message.toJSONString();
                   JSONObject jsonObject = JSONArray.parseObject(s);
                   Object dataObject = jsonObject.get("data");
                   String dataObjectStr = JSONObject.toJSONString(dataObject);
                   JSONArray dataArray = JSONArray.parseArray(dataObjectStr);
                   String group = equipmentGroupMap.getOrDefault(get_sn, "");
                   //处理采集数据
//                   if (group.equals("西门子")) {
//                       parseXMZ(dataArray, get_sn);
//                   } else if (group.equals("科德")) {
//                       parseKD(dataArray, get_sn);
//                   } else if (group.equals("海德汉")) {
//                       parseHDH(dataArray, get_sn);
//                   }
                }
            } else if (topic.contains("disconnected")) {
                //Thread.sleep(1000 * 25);
                String[] tmp = topic.split("/");
                String sn = tmp[4];
                String topics = "$SYS/brokers/emqx@192.168.32.107/clients/";
                String s = "/disconnected";
                String s1 = message.toJSONString();
                System.out.println("topic = " + topic);

            }
        }
    }
}
